package com.tengju.bff.interfaces.covercharge.util;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 日期工具类
 * 
 * @author zhaoyi
 */
public abstract class DateTimeUtils extends DateUtils {

	/**
	 * Default time format : yyyy-MM-dd HH:mm:ss
	 */
	public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

	/**
	 * Time format : yyyy-MM-dd HH:mm
	 */
	public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
	public static final String TIME_FORMAT = "HH:mm";

	/**
	 * Default date format
	 */
	public static final String DATE_FORMAT = "yyyy-MM-dd";
	/**
	 * Default month format
	 */
	public static final String MONTH_FORMAT = "yyyy-MM";
	/**
	 * Default day format
	 */
	public static final String DAY_FORMAT = "dd";

	// Date pattern, demo: 2013-09-11
	public static final String DATE_PATTERN = "^[0-9]{4}\\-[0-9]{2}\\-[0-9]{2}$";

	private DateTimeUtils() {
	}

	public static boolean isDate(String dateAsText) {
		return StringUtils.isNotEmpty(dateAsText) && dateAsText.matches(DATE_PATTERN);
	}

	/**
	 * 功能描述: <br>
	 * 获取当前时间
	 *
	 * @return
	 */
	public static Date now() {
		return new Date();
	}

	/**
	 * 解析：指定日期字符串
	 * 
	 * @param strDate
	 * @param strFormat 日期格式
	 * @return Date
	 */
	public static Date parseStringAsDate(String strDate, String strFormat) {
		Date date = null;
		DateFormat dateFormat = new SimpleDateFormat(strFormat);
		try {
			date = dateFormat.parse(strDate);
		} catch (ParseException e) {
		}
		return date;
	}

	/**
	 * 功能描述: <br>
	 * 指定日期字符串 yyyy-MM-dd HH:mm:ss格式
	 *
	 * @param strDate
	 * @return
	 */
	public static Date parseStringToDate(String strDate) {
		return parseStringAsDate(strDate, DEFAULT_DATE_TIME_FORMAT);
	}

	/**
	 * 解析：指定Date
	 * 
	 * @return String
	 */
	public static String parseDateAsString(Date date, String strFormat) {

		if(date ==null){
			return "";
		}

		String strResult = "";
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(strFormat);
		strResult = simpleDateFormat.format(date);
		return strResult;
	}

	public static String toDateText(Date date) {
		return toDateText(date, DATE_FORMAT);
	}

	public static String toDateText(Date date, String pattern) {
		if (date == null || pattern == null) {
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
		return dateFormat.format(date);
	}

	/**
	 * 日期格式转换为字符串 ，结果：yyyy-MM-dd
	 * 
	 * @param date
	 * @return
	 */
	public static String dateParseShortString(Date date) {
		DateFormat df = new SimpleDateFormat(DATE_FORMAT);
		return df.format(date);
	}

	/**
	 * 日期格式转换为字符串，结果：yyyy-MM-dd HH:mm:ss
	 * 
	 * @param date
	 * @return
	 */
	public static String dateParseString(Date date) {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return df.format(date);
	}
	
	/**
	 * 功能描述: <br>
	 * 获取指定日期所在月份的第一天
	 *
	 * @param sourceDate
	 * @return
	 */
	public static Date getMonthFirstDay(Date sourceDate) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(sourceDate);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 功能描述: <br>
	 * 获取指定日期所在月份的最后一天
	 *
	 * @param sourceDate
	 * @return
	 */
	public static Date getMonthLastDay(Date sourceDate) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(sourceDate);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}
	
	/**
	 * 获取当月第一天yyyy-MM-dd HH:mm:ss
	 */
	public static String getFirstDayOfMonth(){
		Calendar cal = Calendar.getInstance(); 
		SimpleDateFormat datef=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
         //当前月的第一天             
        cal.set(GregorianCalendar.DAY_OF_MONTH, 1);   
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        Date beginTime1=cal.getTime();  
        String beginTime=datef.format(beginTime1);  
        return beginTime;
	}
	
	/**
     * 获取当月最后一天 yyyy-MM-dd HH:mm:ss
     */
    public static String getLastDayOfMonth(){
        Calendar cal = Calendar.getInstance(); 
        SimpleDateFormat datef=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        cal.set(GregorianCalendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));   
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);
        Date beginTime1=cal.getTime();  
        String beginTime=datef.format(beginTime1);  
        return beginTime;
    }

	/**
	 * 获取指定日期年第一天
	 */
	public static Date getFirstDayOfYear(Date sourceDate){
		Calendar cal = Calendar.getInstance();
		cal.setTime(sourceDate);

		cal.set(GregorianCalendar.DAY_OF_YEAR, cal.getActualMinimum(Calendar.DAY_OF_YEAR));
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	/**
	 * 获取指定日期年最后一天
	 */
	public static Date getLastDayOfYear(Date sourceDate){
		Calendar cal = Calendar.getInstance();
		cal.setTime(sourceDate);

		cal.set(GregorianCalendar.DAY_OF_YEAR, cal.getActualMaximum(Calendar.DAY_OF_YEAR));
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);
		return cal.getTime();
	}

	/**
	 * 获取当年最后一天
	 */
	public static Date getLastDayOfYear(){
		Calendar cal = Calendar.getInstance();
		cal.set(GregorianCalendar.DAY_OF_YEAR, cal.getActualMaximum(Calendar.DAY_OF_YEAR));
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);
		return cal.getTime();
	}

	/**
	 * 获取给定日的最后一刻。
	 * 
	 * @param when
	 *            给定日
	 * @return 最后一刻。例如：2006-4-19 23:59:59.999
	 */
	public static Date getDayEnd(Date when) {
		Date date = truncate(when, Calendar.DATE);
		date = addDays(date, 1);
		date.setTime(date.getTime() - 1);
		return date;
	}

	public static Date getDate(String dateText) {
		return getDate(dateText, DATE_FORMAT);
	}

	public static Date getDate(String dateText, String pattern) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
		try {
			return dateFormat.parse(dateText);
		} catch (ParseException e) {
			throw new IllegalStateException("Parse date from [" + dateText + "," + pattern + "] failed", e);
		}
	}

	public static String toDateTime(Date date) {
		return toDateText(date, DATE_TIME_FORMAT);
	}

	/**
	 * 日期加法
	 * 
	 * @param when
	 *            被计算的日期
	 * @param field
	 *            the time field. 在Calendar中定义的常数，例如Calendar.DATE
	 * @param amount
	 *            加数
	 * @return 计算后的日期
	 */
	public static Date add(Date when, int field, int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(when);
		calendar.add(field, amount);
		return calendar.getTime();
	}

	/**
	 * 计算给定的日期加上给定的天数。
	 * 
	 * @param when
	 *            给定的日期
	 * @param amount
	 *            给定的天数
	 * @return 计算后的日期
	 */
	public static Date addDays(Date when, int amount) {

		return add(when, Calendar.DAY_OF_YEAR, amount);
	}
	
	/**
	 * 功能描述: <br>
	 * 获取前N天零点的时间
	 *
	 * @param when
	 * @param day
	 * @return
	 */
	public static String lastDays(Date when, int day) {
		Date date=add(when, Calendar.DAY_OF_YEAR, -day);
		Calendar calendar=Calendar.getInstance(); 
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return parseDateAsString(calendar.getTime(), DEFAULT_DATE_TIME_FORMAT);
	}
	
	/**
	 * 功能描述: <br>
	 * 获取前N月零点的时间
	 *
	 * @param when
	 * @param month
	 * @return
	 */
	public static String lastMonths(Date when, int month) {
		Date date=add(when, Calendar.MONTH, -month);
		Calendar calendar=Calendar.getInstance(); 
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return parseDateAsString(calendar.getTime(), DEFAULT_DATE_TIME_FORMAT);
	}

	/**
	 * Return current year.
	 *
	 * @return Current year
	 */
	public static int currentYear() {
		return calendar().get(Calendar.YEAR);
	}

	public static Calendar calendar() {
		return Calendar.getInstance();
	}

	public static String getNowDateyyyyMMddHHmmss() {
		String strResult = "";
		String strFormat = "yyyyMMddHHmmss";
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(strFormat);
		Calendar calendar = Calendar.getInstance();
		strResult = simpleDateFormat.format(calendar.getTime());
		return strResult;
	}

	public static int daysOfTwo(Date startDate, Date endDate) {
		if (null == startDate || null == endDate) {
			return -1;
		}
		return (int) ((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
	}

	public static int minitesOfTwo(Date startDate, Date endDate) {
		if (null == startDate || null == endDate) {
			return -1;
		}
		return (int) ((endDate.getTime() - startDate.getTime()) / (1000 * 60));
	}
	
	/**
	 * 获取当前日期的0点
	 * @return
	 */
	public static Date getToday() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}
	
	/**
	 * 当日顺延7天
	 * 
	 * @return
	 */
	public static Date getTodayNextSeven() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getToday());
		cal.add(Calendar.DATE, 7);
		return cal.getTime();
	}

	public static Date getThisWeekMonday() {
		Calendar cal = Calendar.getInstance();
		// 获得当前日期是一个星期的第几天
		int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
		if (1 == dayWeek) {
			cal.add(Calendar.DAY_OF_MONTH, -1);
		}
		// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		// 获得当前日期是一个星期的第几天
		int day = cal.get(Calendar.DAY_OF_WEEK);
		// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
		cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	/**
	 * 得到本周周日
	 * 
	 * @return yyyy-MM-dd
	 */
	public static Date getThisWeekSunday() {
		Calendar c = Calendar.getInstance();
		int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
		if (day_of_week == 0)
			day_of_week = 7;
		c.add(Calendar.DATE, -day_of_week + 7);
		
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MILLISECOND, 999);
		return c.getTime();
	}

	/**
	 * 下周一
	 * 
	 * @return
	 */
	public static Date getNextWeekMonday() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekMonday());
		cal.add(Calendar.DATE, 7);
		return cal.getTime();
	}

	/**
	 * 下周日
	 * 
	 * @return
	 */
	public static Date getNextWeekSunday() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekSunday());
		cal.add(Calendar.DATE, 7);
		return cal.getTime();
	}
	
	  /**
     * 获取知道日期是星期几<br>
     * 
     * @param dt
     * @return 
     */
    public static String getWeekOfDate(Date dt) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);

        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0){
            w = 0;
        }

        return weekDays[w];
    }


	/**
	 * Date转LocalDateTime
	 *
	 * @param date Date
	 * @return LocalDateTime
	 */
	public static LocalDateTime dateToLocalDateTime(Date date) {
		try {
			Instant instant = date.toInstant();
			ZoneId zoneId = ZoneId.systemDefault();
			return instant.atZone(zoneId).toLocalDateTime();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 转换String
	 *
	 * @param dateTime 时间
	 * @return StringTime
	 */
	public static String parseLocalDateTimeToString(LocalDateTime dateTime) {

		if(dateTime == null){
			return "";
		}
		DateTimeFormatter fmt = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT);
		return fmt.format(dateTime);
	}

	public static void main(String[] args) {
		System.out.println(getLastDayOfYear());
	}

	/**
	 * LocalDateTime转Date
	 *
	 * @param localDateTime LocalDateTime
	 * @return Date
	 */
	public static Date localDateTimeToDate(LocalDateTime localDateTime){
		try {
			ZoneId zoneId = ZoneId.systemDefault();
			ZonedDateTime zdt = localDateTime.atZone(zoneId);
			return Date.from(zdt.toInstant());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}